import pytest

from flaskbb.auth.services.registration import (
    EmailUniquenessValidator,
    UsernameRequirements,
    UsernameUniquenessValidator,
    UsernameValidator,
)
from flaskbb.core.auth.registration import UserRegistrationInfo
from flaskbb.core.exceptions import ValidationError
from flaskbb.user.models import User

pytestmark = pytest.mark.usefixtures("default_settings")


def test_raises_if_username_too_short():
    requirements = UsernameRequirements(min=4, max=100, blacklist=set())
    validator = UsernameValidator(requirements)

    registration = UserRegistrationInfo(
        username="no", password="no", email="no@no.no", group=4, language="no"
    )

    with pytest.raises(ValidationError) as excinfo:
        validator(registration)

    assert excinfo.value.attribute == "username"
    assert "must be between" in excinfo.value.reason


def test_raises_if_username_too_long():
    requirements = UsernameRequirements(min=0, max=1, blacklist=set())
    validator = UsernameValidator(requirements)

    registration = UserRegistrationInfo(
        username="no", password="no", email="no@no.no", group=4, language="no"
    )

    with pytest.raises(ValidationError) as excinfo:
        validator(registration)

    assert excinfo.value.attribute == "username"
    assert "must be between" in excinfo.value.reason


def test_raises_if_username_in_blacklist():
    requirements = UsernameRequirements(min=1, max=100, blacklist=set(["no"]))
    validator = UsernameValidator(requirements)

    registration = UserRegistrationInfo(
        username="no", password="no", email="no@no.no", group=4, language="no"
    )

    with pytest.raises(ValidationError) as excinfo:
        validator(registration)

    assert excinfo.value.attribute == "username"
    assert "forbidden username" in excinfo.value.reason


# fred's back. :(
def test_raises_if_user_already_registered(Fred):
    validator = UsernameUniquenessValidator(User)
    registration = UserRegistrationInfo(
        username="fred",
        email="fred@fred.fred",
        language="fred",
        group=4,
        password="fred",
    )

    with pytest.raises(ValidationError) as excinfo:
        validator(registration)

    assert excinfo.value.attribute == "username"
    assert "already registered" in excinfo.value.reason


def test_raises_if_user_email_already_registered(Fred):
    validator = EmailUniquenessValidator(User)
    registration = UserRegistrationInfo(
        username="fred",
        email="fred@fred.fred",
        language="fred",
        group=4,
        password="fred",
    )

    with pytest.raises(ValidationError) as excinfo:
        validator(registration)

    assert excinfo.value.attribute == "email"
    assert "already registered" in excinfo.value.reason
